package main

import (
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path"
	"strings"

	"github.com/hashicorp/go-hclog"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
	sms "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms/v20210111"
	"github.com/yaoapp/kun/grpc"
	jpushclient "github.com/ylywyn/jpush-api-go-client"
)

type NotificationPlugin struct{ grpc.Plugin }

var appKey = "8c3c69a086cf7cbf48dfda4e"
var secret = "f3b696745567eccf293cb596"

func (demo *NotificationPlugin) setLogFile() {
	var output io.Writer = os.Stdout
	//开启日志
	logroot := os.Getenv("GOU_TEST_PLG_LOG")
	if logroot == "" {
		logroot = "./logs"
	}
	if logroot != "" {
		logfile, err := os.OpenFile(path.Join(logroot, "plugin.log"), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
		if err == nil {
			output = logfile
		}
	}
	demo.Plugin.SetLogger(output, grpc.Info)
}

var secretId = "AKIDMgmhO1Uox58zfAUccR3RbXEiy2ucBb3V"
var secretKey = "NYWGm6CFHA1lJix5BA362mZEf6ayBAwV"

func (noti *NotificationPlugin) SendSms(phoneNumbers []*string, templateIdSet []string, args ...interface{}) (string, error) {
	noti.Logger.Info("secretId", secretId)
	credential := common.NewCredential(
		secretId,
		secretKey,
	)
	// SecretId:AKIDMgmhO1Uox58zfAUccR3RbXEiy2ucBb3V
	//SecretKey:NYWGm6CFHA1lJix5BA362mZEf6ayBAwV
	// 实例化一个client选项，可选的，没有特殊需求可以跳过
	cpf := profile.NewClientProfile()
	cpf.HttpProfile.Endpoint = "sms.tencentcloudapi.com"
	// 实例化要请求产品的client对象,clientProfile是可选的
	client, _ := sms.NewClient(credential, "ap-beijing", cpf)

	// 实例化一个请求对象,每个接口都会对应一个request对象
	request := sms.NewSendSmsRequest()

	request.PhoneNumberSet = phoneNumbers // common.StringPtrs([]string{"18874951720"})
	// appid is null, so use default
	if len(args) > 0 {
		request.SmsSdkAppId = common.StringPtr(args[0].(string))
		request.TemplateId = common.StringPtr(args[1].(string))
		request.SignName = common.StringPtr(args[2].(string))
	} else {
		request.SmsSdkAppId = common.StringPtr("1400954099")
		request.TemplateId = common.StringPtr("2357667")
		request.SignName = common.StringPtr("九章注北京科技")
	}
	request.TemplateParamSet = common.StringPtrs(templateIdSet)

	// 返回的resp是一个SendSmsResponse的实例，与请求对象对应
	response, err := client.SendSms(request)
	if err != nil {
		if _, ok := err.(*errors.TencentCloudSDKError); ok {
			fmt.Printf("An API error has returned: %s", err)
			noti.Logger.Log(hclog.Error, "An API error has returned", err)
		}
		return "send failure", err
	}
	noti.Logger.Log(hclog.Error, response.ToJsonString())

	// 输出json格式的字符串回包
	// fmt.Printf("%s", response.ToJsonString())
	return response.ToJsonString(), nil
}

func (noti *NotificationPlugin) PushNoti(regIDs []string, alert, title, content string) (string, error) {
	// Platform
	var pf jpushclient.Platform
	pf.Add(jpushclient.ANDROID)
	pf.Add(jpushclient.IOS)
	pf.Add(jpushclient.WINPHONE)

	var ad jpushclient.Audience
	ad.SetID(regIDs)

	// Notice
	var notice jpushclient.Notice
	notice.SetAlert("alert_test")
	notice.SetAndroidNotice(&jpushclient.AndroidNotice{Alert: "AndroidNotice"})
	notice.SetIOSNotice(&jpushclient.IOSNotice{Alert: "IOSNotice"})
	notice.SetWinPhoneNotice(&jpushclient.WinPhoneNotice{Alert: "WinPhoneNotice"})

	var msg jpushclient.Message
	msg.Title = title
	msg.Content = content

	// Payload
	payload := jpushclient.NewPushPayLoad()
	payload.SetPlatform(&pf)
	payload.SetAudience(&ad)
	payload.SetMessage(&msg)
	payload.SetNotice(&notice)

	// Convert Payload to Bytes
	bytes, _ := payload.ToBytes()
	fmt.Printf("%s\r\n", string(bytes))

	noti.Logger.Log(hclog.Info, "appKey", appKey)
	// Push
	c := jpushclient.NewPushClient(secret, appKey)
	str, err := c.Send(bytes)
	if err != nil {
		fmt.Printf("err:%s", err.Error())
		return "error", err
	}
	noti.Logger.Log(hclog.Info, "ok", regIDs)
	return str, err
}
func (noti *NotificationPlugin) Exec(name string, args ...interface{}) (*grpc.Response, error) {
	noti.Logger.Log(hclog.Info, "plugin method called", name)
	noti.Logger.Log(hclog.Info, "args", args)

	var v = make(map[string]interface{})
	switch name {
	case "sms":
		if len(args) < 2 {
			v = map[string]interface{}{"code": 400, "message": "参数不足，需要一个参数，需要手机号以及发送码"}
			break
		}
		//通地分隔符“，”，字符串转字符串切片
		phonenumbers := strings.Split(args[0].(string), ",")
		templateIdSet := strings.Split(args[1].(string), ",")
		// phonenumbers, ok := args[0].([]string)
		if len(args) > 2 { // args[1] : 1400954099
			if len(args) > 5 { // args[4] : []string{"1234", "1"}
				secretId = args[5].(string)
				secretKey = args[6].(string)
			}
			appid := args[2].(string)
			templateId := args[3].(string)
			signName := args[4].(string)

			msg, err := noti.SendSms(common.StringPtrs(phonenumbers), templateIdSet, appid, templateId, signName)
			if err != nil {
				v = map[string]interface{}{"code": 400, "message": err.Error()}
			}
			v = map[string]interface{}{"code": 200, "message": msg}
		} else { // args = 2 only
			msg, err := noti.SendSms(common.StringPtrs(phonenumbers), templateIdSet)
			if err != nil {
				v = map[string]interface{}{"code": 400, "message": err.Error()}
			}
			v = map[string]interface{}{"code": 200, "message": msg}
		}

	case "push":
		if len(args) < 1 {
			v = map[string]interface{}{"code": 400, "message": "参数不足，需要一个参数push userid"}
			break
		}
		if len(args) > 4 {
			secret = args[4].(string)
			appKey = args[5].(string)
		}
		regids := strings.Split(args[0].(string), ",")
		str, err := noti.PushNoti(regids, args[1].(string), args[2].(string), args[3].(string))
		if err != nil {
			v = map[string]interface{}{"code": 400, "message": err.Error()}
		} else {
			v = map[string]interface{}{"code": 200, "message": str}
		}

	default:
		v = map[string]interface{}{"code": 300, "name": name, "args": args}
	}
	//输出前需要转换成字节
	bytes, err := json.Marshal(v)
	if err != nil {
		return nil, err
	}
	//设置输出数据的类型
	//支持的类型：map/interface/string/integer,int/float,double/array,slice
	return &grpc.Response{Bytes: bytes, Type: "map"}, nil
}
func main() {

	plugin := &NotificationPlugin{}
	plugin.setLogFile()
	grpc.Serve(plugin)
}

// 调试时开启，需要直接调试时修改成main
func mainpush() {
	plugin := &NotificationPlugin{}
	plugin.setLogFile()
	// grpc.Serve(plugin) 不要使用server
	// rep, err := plugin.Exec("push", []string{"18229950130"}) //普通的go程序，用于开发调试
	rep, err := plugin.Exec("push", []string{"18229950130"}) //普通的go程序，用于开发调试
	fmt.Println(rep, err)
}

func mainsms() {
	plugin := &NotificationPlugin{}
	plugin.setLogFile()
	// grpc.Serve(plugin) 不要使用server
	rep, err := plugin.Exec("sms", "18229950130,13975104216", "8888,1")
	// rep, err := plugin.Exec("sms", "18229950130,13975104216", "8888,1", "1400954099", "2357667", "九章注北京科技") //普通的go程序，用于开发调试
	fmt.Println(rep, err)
}
